Skip to content

Implement R-GCIP Token-Only Session via ExchangeToken #14986

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

srushtisv
Copy link
Contributor

Description

This PR introduces support for a "token-only" session mode, primarily for Bring Your Own CIAM (BYO-CIAM) use cases with Regionalized GCIP (R-GCIP). This allows developers to use Firebase services with a Firebase token obtained from a third-party OIDC provider, without creating a User entity or a standard Firebase Auth session.

Key Changes

  • New Public API (Auth.exchangeToken): Adds exchangeToken(idToken:idpConfigId:completion:) and its async counterpart. This method exchanges a third-party OIDC ID token for a Firebase ID token.
  • Token-Only Session State: A new private property, _rGCIPFirebaseToken, has been added to the Auth class to store the token returned from exchangeToken. This state is mutually exclusive with currentUser.
  • AuthInterop Modification: The getToken(forcingRefresh:completion:) method in the AuthInterop extension has been updated. It now first checks for an active R-GCIP token session.
    • If an active, non-expired token exists, it is returned.
    • If the token is expired or forceRefresh is true, an AuthErrorCode.userTokenExpired error is returned, signaling that the developer must call exchangeToken again.
    • If no R-GCIP token exists, the logic falls back to the original implementation using currentUser.
  • State Invalidation: Standard sign-in flows (e.g., signInWithEmail:password:) now clear the R-GCIP token session to prevent conflicting states.
  • Unit Tests: Added a new test suite, ExchangeTokenRequestTests.swift, to validate the URL construction and body of the new API request. Updated AuthTests.swift to cover the new AuthInterop logic paths.

Changelog

  • Added support to Auth.exchangeToken(idToken:idpConfigId:completion:) R-GCIP sessions by exchanging a third-party OIDC token for a Firebase token.
  • The AuthInterop protocol now supports a token-only authentication state, which is activated by a successful exchangeToken call.

Copy link
Contributor

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

@srushtisv srushtisv changed the base branch from main to byociam-sample-app-implementation June 15, 2025 21:39
@google-oss-bot
Copy link

1 Warning
⚠️ Did you forget to add a changelog entry? (Add #no-changelog to the PR description to silence this warning.)

Generated by 🚫 Danger

@srushtisv srushtisv self-assigned this Jun 16, 2025
@srushtisv srushtisv requested a review from pashanka June 16, 2025 07:53
@srushtisv srushtisv marked this pull request as ready for review June 16, 2025 07:53
@srushtisv srushtisv requested a review from ncooke3 June 16, 2025 07:57
private var _rGCIPFirebaseToken: FirebaseToken?

/// A lock to ensure thread-safe access to the R-GCIP token state.
private let rGCIPStateLock = NSLock()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying adding import FirebaseCoreInternal and try using the FIRAllocatedUnfairLock type which should combine the token and token lock into one property.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure Nick, updated the code.

if let token = rGCIPToken {
/// If a token exists, this session is active. Check for expiration.
if forceRefresh || token.expirationDate < Date() {
let errorMessage = forceRefresh ? "A new token was requested via forceRefresh." :
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shoul the error message say forceRefresh is not supported

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes Pavan, updated this.

@srushtisv srushtisv requested review from pashanka and ncooke3 June 23, 2025 21:25
@srushtisv srushtisv force-pushed the byociam-sample-app-implementation branch from 80647da to 859ec86 Compare June 24, 2025 08:25
@srushtisv srushtisv force-pushed the byociam-auth-interop branch from 7ac16e2 to 955cc5e Compare June 24, 2025 08:29
@srushtisv srushtisv force-pushed the byociam-sample-app-implementation branch from a42c578 to d958c95 Compare June 24, 2025 12:37
@srushtisv srushtisv force-pushed the byociam-auth-interop branch from 955cc5e to d9dfa0d Compare June 24, 2025 13:04
}
}
#endif
guard let self = self else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
guard let self = self else {
guard let self else {

}
#endif
guard let self = self else {
DispatchQueue.main.async { callback(nil, nil) }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would using any of the Auth.wrapMainAsync APIs work here?

/// Clear any R-GCIP session state when a standard user signs in. This ensures we exit
/// Token-Only Mode.
self.rGCIPFirebaseTokenLock.withLock { $0 = nil }
/// ... rest of original function
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// ... rest of original function

/// GCIP, where no `User` object is created. It is mutually exclusive with `_currentUser`.
/// If the wrapped value is non-nil, the `AuthInterop` layer will use it for token generation
/// instead of relying on a `currentUser`.
private var rGCIPFirebaseTokenLock = FIRAllocatedUnfairLock<FirebaseToken?>(initialState: nil)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FIRAllocatedUnfairLock is a class. It's instances should be a constant.

Suggested change
private var rGCIPFirebaseTokenLock = FIRAllocatedUnfairLock<FirebaseToken?>(initialState: nil)
private let rGCIPFirebaseTokenLock = FIRAllocatedUnfairLock<FirebaseToken?>(initialState: nil)

}

/// Regionalized auth
// MARK: Regionalized auth
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not: the added dash adds a horizontal line divider in Xcode

Suggested change
// MARK: Regionalized auth
// MARK: - Regionalized auth

@srushtisv
Copy link
Contributor Author

duplicated in #15041

@srushtisv srushtisv closed this Jun 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants